<template>
  <span>
    {{ lastTime | format }}
  </span>
</template>

<script>

function fixedZero (val) {
  return val * 1 < 10 ? `0${val}` : val
}

export default {
  name: 'CountDown',
  props: {
    format: {
      type: Function,
      default: undefined
    },
    target: {
      type: [Date, Number],
      required: true
    },
    onEnd: {
      type: Function,
      default: () => ({})
    }
  },
  data () {
    return {
      dateTime: '0',
      originTargetTime: 0,
      lastTime: 0,
      timer: 0,
      interval: 1000
    }
  },
  filters: {
    format (time) {
      const hours = 60 * 60 * 1000
      const minutes = 60 * 1000

      const h = Math.floor(time / hours)
      const m = Math.floor((time - h * hours) / minutes)
      const s = Math.floor((time - h * hours - m * minutes) / 1000)
      return `${fixedZero(h)}:${fixedZero(m)}:${fixedZero(s)}`
    }
  },
  created () {
    this.initTime()
    this.tick()
  },
  methods: {
    initTime () {
      let lastTime = 0
      let targetTime = 0
      this.originTargetTime = this.target
      try {
        if (Object.prototype.toString.call(this.target) === '[object Date]') {
          targetTime = this.target
        } else {
          targetTime = new Date(this.target).getTime()
        }
      } catch (e) {
        throw new Error('invalid target prop')
      }

      lastTime = targetTime - new Date().getTime()

      this.lastTime = lastTime < 0 ? 0 : lastTime
    },
    tick () {
      const { onEnd } = this

      this.timer = setTimeout(() => {
        if (this.lastTime < this.interval) {
          clearTimeout(this.timer)
          this.lastTime = 0
          if (typeof onEnd === 'function') {
            onEnd()
          }
        } else {
          this.lastTime -= this.interval
          this.tick()
        }
      }, this.interval)
    }
  },
  beforeUpdate () {
    if (this.originTargetTime !== this.target) {
      this.initTime()
    }
  },
  beforeDestroy () {
    clearTimeout(this.timer)
  }
}
</script>

<style scoped>

</style>
